package tr.edu.ege.seagent.hobnobontology.instance;

import java.util.List;
import tr.edu.ege.seagent.hobnobontology.schema.HobNobVocabulary;
import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.tdb.TDBFactory;

public class HobNobTDBStore {

	/**
	 * x-Coordinate of the Istanbul.
	 */
	public static final double ISTANBUL_X_COORDINATE = 41.044372;

	/**
	 * y-Coordinate of the Istanbul.
	 */
	public static final double ISTANBUL_Y_COORDINATE = 29.035256;
	/**
	 * File path for where TDB Store is created.
	 */
	public static final String MODEL_DIRECTORY = "/home/etmen/workspace/Yanyanayiz.biz/StoreTDB/";
	/**
	 * Notification message for Istanbul URI
	 * 
	 */
	public static final String MSG_ISTANBUL_NOTIFICATION = "Boğaz Köprüsü'nde birlikteler";
	/**
	 * Model that we want to store.
	 */
	private Model sampleModel;
	/**
	 * Stored model.
	 */
	private Model tdbModel;

	private Dataset dataset;

	/**
	 * Instance creator to construct the sample model.
	 */
	private HobNobInstanceCreator creator;

	public HobNobTDBStore() {

		this.sampleModel = new HobNobSampleModelCreator().createNewInstance();

	}

	public HobNobTDBStore(Model sampleModel) {
		this.sampleModel = sampleModel;
		this.tdbModel = createTDBStore();
		creator = new HobNobInstanceCreator(tdbModel);
	}

	/**
	 * This method provide us to add new statement to the TDB Store.
	 * 
	 * @return
	 * 
	 */
	public Model addNewStatementToTDBStore() {

		// add notification statements to the stored model...
		istanbulNotificationStatements(creator);
		// add location statements to the stored model...
		istanbulLocationStatements(creator);
		tdbModel.commit();

		return tdbModel;
	}

	public Model createIstanbulStatements() {
		Model istanbulModel = ModelFactory.createDefaultModel();
		
		HobNobInstanceCreator HobNobCreator = new HobNobInstanceCreator(istanbulModel);
		
		// add notification statements to the stored model...
		istanbulNotificationStatements(HobNobCreator);
		// add location statements to the stored model...
		istanbulLocationStatements(HobNobCreator);
		
		return istanbulModel;
	}


	/**
	 * Creates literals and resources of the location statements.
	 * @param hobNobInstanceCreator TODO
	 */
	public void istanbulLocationStatements(HobNobInstanceCreator hobNobInstanceCreator) {
		// create LOCATION_ISTANBUL_URI instance of LOCATION_URI
		hobNobInstanceCreator.createInstance(HobNobInstanceVocabulary.LOCATION_ISTANBUL_URI,
				HobNobVocabulary.LOCATION_URI);
		// add x-Coordinate of Istanbul location...
		hobNobInstanceCreator.createLiteralStatement(
				HobNobInstanceVocabulary.LOCATION_ISTANBUL_URI,
				HobNobVocabulary.X_COORDINATE, ISTANBUL_X_COORDINATE);
		// add y-Coordinate of Istanbul location...
		hobNobInstanceCreator.createLiteralStatement(
				HobNobInstanceVocabulary.LOCATION_ISTANBUL_URI,
				HobNobVocabulary.Y_COORDINATE, ISTANBUL_Y_COORDINATE);
		// add dbpedia resource to Istanbul location...
		hobNobInstanceCreator.createResourceStatement(
				HobNobInstanceVocabulary.LOCATION_ISTANBUL_URI,
				HobNobVocabulary.LOCATION_HAS_DBPEDIA_URI,
				HobNobInstanceVocabulary.ISTANBUL_URI);
	}

	/**
	 * Creates literals and resources of the notification statements.
	 * @param hobNobInstanceCreator TODO
	 */
	public void istanbulNotificationStatements(HobNobInstanceCreator hobNobInstanceCreator) {
		
		// create NOTIFICATION_ISTANBUL_URI instance of NOTIFICATION_URI...
		hobNobInstanceCreator.createInstance(
				HobNobInstanceVocabulary.NOTIFICATION_ISTANBUL_URI,
				HobNobVocabulary.NOTIFICATION_URI);

		// add notification message as a literal...
		hobNobInstanceCreator.createLiteralStatement(
				HobNobInstanceVocabulary.NOTIFICATION_ISTANBUL_URI,
				HobNobVocabulary.NOTIFICATION_MESSAGE_URI,
				MSG_ISTANBUL_NOTIFICATION);
		// add notification has member statement...
		hobNobInstanceCreator.createResourceStatement(
				HobNobInstanceVocabulary.NOTIFICATION_ISTANBUL_URI,
				HobNobVocabulary.NOTIFICATION_HAS_MEMBER_URI,
				HobNobInstanceVocabulary.MEMBER_BAHTI_URI);
		// add notification has member statement...
		hobNobInstanceCreator.createResourceStatement(
				HobNobInstanceVocabulary.NOTIFICATION_ISTANBUL_URI,
				HobNobVocabulary.NOTIFICATION_HAS_MEMBER_URI,
				HobNobInstanceVocabulary.MEMBER_CEREN_URI);
		// add notification at location statement...
		hobNobInstanceCreator.createResourceStatement(
				HobNobInstanceVocabulary.NOTIFICATION_ISTANBUL_URI,
				HobNobVocabulary.NOTIFICATION_AT_LOCATION_URI,
				HobNobInstanceVocabulary.LOCATION_ISTANBUL_URI);
	}

	/**
	 * This method provide us to create new TDB store with given sample model.
	 * 
	 * @return created or connectted model
	 */

	public Model createTDBStore() {
		// if tdb-store is nonexistent create new one. If tdb-store is exist
		// connect to the dataset
		dataset = TDBFactory.createDataset(MODEL_DIRECTORY);
		// get model from tdb-store
		tdbModel = dataset.getDefaultModel();
		// add sample model to tdb store...
		tdbModel.add(sampleModel);
		// commit tdb model
		tdbModel.commit();
		// close tdb model to avoid any change in...
		tdbModel.close();

		return tdbModel;

	}

	/**
	 * This method provide us to search notification at location has more than
	 * three million population which stored in TDB-store
	 * 
	 * @return list of resources
	 */
	public List<Resource> searchNotificationsFromTDBStore() {
		
		HobNobModelSearcher searcher = new HobNobModelSearcher(tdbModel);


		return searcher
				.searchNotificationAtLocationHasMoreThanThreeMillionPopulation();
	}

}
